#define _SPI_MODULE_
#include "spidevice.h"

#define  SPI_R_MODE        0
#define  SPI_W_MODE        1
#define  SPI_RW_MODE       2

volatile uint16_t SpiLen;
volatile uint8_t SpiRWMode;
volatile uint8_t *pSpiDes;
volatile uint8_t *pSpiSrc;

/*****************************************************************************//*!
   *
   * @brief SPI interrupt.     
   * @param[in]  none.
   * @return  none.
   *
   * @ Pass/ Fail criteria: none.
   *****************************************************************************/
void SPI0_IRQHandler()
{
	volatile uint8_t DataClr;
	
	SpiLen--;
	
	DataClr = SPI0->S;
	
	switch(SpiRWMode)
	{
		case SPI_R_MODE:
			*pSpiDes++ = SPI0->D;
			if(SpiLen != 0)
				SPI0->D = 0x55;
			else
			{
				SPI_SS_DISABLE();
				SPI_IntDisable(SPI0);
				SpiSt = SPI_IDLE;
			}
			break;
		case SPI_W_MODE:
			DataClr = SPI0->D;
			if(SpiLen != 0)
				SPI0->D = *pSpiSrc++;
			else
			{
				SPI_SS_DISABLE();
				SPI_IntDisable(SPI0);
				SpiSt = SPI_IDLE;
			}
			break;
		case SPI_RW_MODE:
			*pSpiDes++ = SPI0->D;
			if(SpiLen != 0)
				SPI0->D = *pSpiSrc++;
			else
			{
				SPI_SS_DISABLE();
				SPI_IntDisable(SPI0);
				SpiSt = SPI_IDLE;
			}
			break;
	}
}
/*****************************************************************************//*!
   *
   * @brief SPI init.
   *        
   * @param[in]  none.
   *
   * @return  none.
   *
   * @ Pass/ Fail criteria: none.
   *****************************************************************************/
void SpiInit()
{
	SPI_SS_DISABLE();
	
	SIM->SCGC |= SIM_SCGC_SPI0_MASK;
	SIM->PINSEL |= SIM_PINSEL_SPI0PS_MASK; 
	
	SPI0->C1 =  (0 << SPI_C1_SPIE_SHIFT)   |
				(1 << SPI_C1_SPE_SHIFT)    |
				(0 << SPI_C1_SPTIE_SHIFT)  |
				(1 << SPI_C1_MSTR_SHIFT)   |
				(1 << SPI_C1_CPOL_SHIFT)   |
				(1 << SPI_C1_CPHA_SHIFT)   |
				(0 << SPI_C1_SSOE_SHIFT)   |
				(0 << SPI_C1_LSBFE_SHIFT)  ;
	
	SPI0->C2 =  (0 << SPI_C2_SPMIE_SHIFT)  | 
				(0 << SPI_C2_MODFEN_SHIFT) |
				(0 << SPI_C2_BIDIROE_SHIFT)|
				(0 << SPI_C2_SPISWAI_SHIFT)|
				(0 << SPI_C2_SPC0_SHIFT)   ;
	
	SPI0->BR =  0x41;                         //div from busclock;
	SPI0->M  =  0;
	
	SpiSt = SPI_IDLE;
	
	NVIC_SetPriority(SPI0_IRQn, 0xFF);
	NVIC_ClearPendingIRQ(SPI0_IRQn);
	NVIC_EnableIRQ( SPI0_IRQn );
}

/*****************************************************************************//*!
   *
   * @brief SPI  read data with interrput mode.
   *        
   * @param[in]  Des - destination pointer.
   * @param[in]  Len - length.
   *
   * @return  none.
   *
   * @ Pass/ Fail criteria: none.
   *****************************************************************************/
void SpiRead(uint8_t *Des,uint16_t Len)
{
	volatile uint8_t Clr;
	
	while(SpiSt == SPI_BUSY);
	SpiSt = SPI_BUSY;
	
	Clr = SPI0->D;
	SPI_SS_ENABLE();
	SpiRWMode = SPI_R_MODE;
	SpiLen = Len;
	pSpiDes = Des;
	SPI0->D = 0x55;
	SPI_IntEnable(SPI0);
}

/*****************************************************************************//*!
   *
   * @brief SPI  send data with interrput mode.
   *        
   * @param[in]  Src - source data pointer.
   * @param[in]  Len - length.
   *
   * @return  none.
   *
   * @ Pass/ Fail criteria: none.
   *****************************************************************************/
void SpiWrite(uint8_t *Src,uint16_t Len)
{
	volatile uint8_t Clr;
	
	while(SpiSt == SPI_BUSY);
	SpiSt = SPI_BUSY;
	
	Clr = SPI0->D;
	SPI_SS_ENABLE();
	SpiRWMode = SPI_W_MODE;
	SpiLen = Len;
	pSpiSrc = Src;
	SPI0->D = *Src++;
	SPI_IntEnable(SPI0);
}

/*****************************************************************************//*!
   *
   * @brief SPI  read and send data with interrput mode.
   *        
   * @param[in]  Des - destination pointer.
   * @param[in]  Src - source data pointer.
   * @param[in]  Len - length.
   *
   * @return  none.
   *
   * @ Pass/ Fail criteria: none.
   *****************************************************************************/
void SpiRW(uint8_t *Des,uint8_t *Src,uint16_t Len)
{
	volatile uint8_t Clr;
	
	while(SpiSt == SPI_BUSY);
	SpiSt = SPI_BUSY;
	Clr = SPI0->S;
	Clr = SPI0->D;
	SPI_SS_ENABLE();
	SpiRWMode = SPI_RW_MODE;
	SpiLen = Len;
	pSpiDes = Des;
	pSpiSrc = Src;
	SPI0->D = *Src++;
	SPI_IntEnable(SPI0);
}

/*****************************************************************************//*!
   *
   * @brief SPI  read and send one byte data with blocking mode.
   *        
   * @param[in]  Data - the data wait for sending.
   *
   * @return  the data received.
   *
   * @ Pass/ Fail criteria: none.
   * @notice  you must close the chip signal yourself
   *****************************************************************************/
uint8_t SpiRWSignal(uint8_t Data)
{
	uint32_t u32Timeout;
	
	while(SpiSt == SPI_BUSY);
	SPI_SS_ENABLE();
	__nop();__nop();__nop();__nop();
	SPI0->D = Data;
	u32Timeout = 0;
	while(((SPI0->S & SPI_S_SPRF_MASK) == 0) && (u32Timeout < 20000))
	{
		u32Timeout++;
	}
	return (SPI0->D);
}

